package com.cloud.user_info.service.impl;

import cn.hutool.crypto.SecureUtil;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.github.pagehelper.PageHelper;
import com.cloud.annex.AnnexUrlService;
import com.cloud.common.constants.ExcelPoiConstants;
import com.cloud.common.constants.GlobalConstants;
import com.cloud.common.domain.Result;
import com.cloud.common.utils.ConfigUtils;
import com.cloud.entity.*;
import com.cloud.common.enums.CheckType;
import com.cloud.common.enums.UserAuthStatus;
import com.cloud.common.enums.UserStatus;
import com.cloud.exception.CustomException;
import com.cloud.scope.DataScope;
import com.cloud.service.RedisService;
import com.cloud.user_info.entity.SysProjectRole;
import com.cloud.user_info.entity.SysUserPost;
import com.cloud.user_info.entity.SysUserProject;
import com.cloud.user_info.entity.vo.OptionUser;
import com.cloud.user_info.entity.vo.ProjectRoleDao;
import com.cloud.user_info.entity.vo.UserBook;
import com.cloud.user_info.mapper.*;
import com.cloud.user_info.service.ISysUserAuthService;
import com.cloud.user_info.service.ISysUserService;
import com.cloud.utils.*;
import jakarta.annotation.Resource;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.web.multipart.MultipartFile;

import java.util.ArrayList;
import java.util.List;
import java.util.concurrent.TimeUnit;

/**
 * 用户 业务层处理
 *
 * @author yzj
 */
@Service
public class SysUserServiceImpl extends ServiceImpl<SysUserMapper, SysUser> implements ISysUserService {

    @Resource
    private SysUserMapper userMapper;

    @Resource
    private SysRoleMapper roleMapper;

    @Resource
    private SysPostMapper postMapper;

    @Resource
    private SysUserPostMapper userPostMapper;

    @Resource
    private SysProjectRoleMapper projectRoleMapper;

    @Resource
    private SysUserProjectMapper userProjectMapper;

    @Resource
    private SysUserAuthMapper userAuthMapper;

    @Resource
    private SysDeptMapper deptMapper;

    @Resource
    private RedisService redisService;

    @Resource
    private AnnexUrlService annexUrlService;

    @Autowired
    private ISysUserAuthService userAuthService;

    /**
     * 根据条件分页查询用户列表
     *
     * @param user 用户信息
     * @return 用户信息集合信息
     */
    @Override
    @DataScope(deptAlias = "d", userAlias = "u")
    public List<SysUser> selectUserList(SysUser user) {
        return userMapper.selectUserList(user);
    }


    /**
     * 查询已分配用户角色列表
     *
     * @param projectRole
     * @return 用户信息集合信息
     */
    @Override
    @DataScope(deptAlias = "d", userAlias = "u")
    public List<SysUser> selectRoleAuthList(ProjectRoleDao projectRole) {
        return userMapper.selectRoleAuthList(projectRole);
    }

    /**
     * 根据账户密码查询账户信息
     *
     * @return 用户对象信息
     */
    @Override
    public SysUser selectUserByLogin(LoginBody loginBody) {
        return userMapper.selectUserByLogin(loginBody);
    }

    /**
     * 通过用户名查询用户
     *
     * @param name
     * @return 用户对象信息
     */
    @Override
    public SysUser selectUserByUserName(String name) {
        return userMapper.selectUserByUserName(name);
    }

    /**
     * 通过用户ID查询用户
     *
     * @param userId 用户ID
     * @return 用户对象信息
     */
    @Override
    public SysUser selectUserById(Long userId) {
        String userKey = String.valueOf(userId);
        SysUser sysUser = redisService.getHashKey(GlobalConstants.sysUserInfo, userKey);
        if (StringUtils.isNull(sysUser)) {
            sysUser = userMapper.selectUserById(userId);
            if (StringUtils.isNotNull(sysUser)) {
                if (StringUtils.isNotEmpty(sysUser.getAvatar())) {
                    sysUser.setAvatar(annexUrlService.getImageTurnPath(sysUser.getAvatar()));
                }
            }
            redisService.setHash(GlobalConstants.sysUserInfo, userKey, sysUser, 24, TimeUnit.HOURS);
        }
        return sysUser;
    }

    /**
     * 查询用户所属角色组
     *
     * @param userName 用户名
     * @return 结果
     */
    @Override
    public String selectUserRoleGroup(String userName) {
        List<SysRole> list = roleMapper.selectRolesByUserName(userName);
        StringBuilder idsStr = new StringBuilder();
        for (SysRole role : list) {
            idsStr.append(role.getRoleName()).append(",");
        }
        if (StringUtils.isNotEmpty(idsStr.toString())) {
            return idsStr.substring(0, idsStr.length() - 1);
        }
        return idsStr.toString();
    }

    /**
     * 查询用户所属岗位组
     *
     * @param userName 用户名
     * @return 结果
     */
    @Override
    public String selectUserPostGroup(String userName) {
        List<SysPost> list = postMapper.selectPostsByUserName(userName);
        StringBuilder idsStr = new StringBuilder();
        for (SysPost post : list) {
            idsStr.append(post.getPostName()).append(",");
        }
        if (StringUtils.isNotEmpty(idsStr.toString())) {
            return idsStr.substring(0, idsStr.length() - 1);
        }
        return idsStr.toString();
    }

    /**
     * 校验用户名称是否唯一
     *
     * @param userName 用户
     * @return 结果
     */
    @Override
    public String checkUserNameUnique(String userName) {
        int count = userMapper.checkUserNameUnique(userName);
        if (count > 0) {
            return CheckType.NOT_UNIQUE.getCode();
        }
        return CheckType.UNIQUE.getCode();
    }

    /**
     * 校验用户名称是否唯一
     *
     * @param user 用户信息
     * @return String
     */
    @Override
    public String checkPhoneUnique(SysUser user) {
        int count = userMapper.checkPhoneUnique(user.getPhone(), user.getUserId());
        if (count > 0) {
            return CheckType.NOT_UNIQUE.getCode();
        }
        return CheckType.UNIQUE.getCode();
    }

    /**
     * 校验email是否唯一
     *
     * @param user 用户信息
     * @return String
     */
    @Override
    public String checkEmailUnique(SysUser user) {
        int count = userMapper.checkEmailUnique(user.getEmail(), user.getUserId());
        if (count > 0) {
            return CheckType.NOT_UNIQUE.getCode();
        }
        return CheckType.UNIQUE.getCode();
    }

    /**
     * 校验用户是否允许操作
     *
     * @param user 用户信息
     */
    @Override
    public void checkUserAllowed(SysUser user) {
        if (StringUtils.isNull(user.getUserId())) {
            throw new CustomException("修改信息主键不能为空");
        }
    }

    /**
     * 新增保存用户信息
     *
     * @param user 用户信息
     * @return 结果
     */
    @Override
    @Transactional
    public Result insertUserInfo(SysUser user) {
        if (StringUtils.isNotEmpty(user.getPassword())) {
            user.setPassword(SecureUtil.md5(user.getPassword()));
        } else {
            String oldPassword = ConfigUtils.getConfigInfo("sys.old.password");
            user.setPassword(SecureUtil.md5(oldPassword));
        }
        user.setStatus(UserStatus.OK.getCode());
        userMapper.insert(user);
        // 新增用户岗位关联
        batchUserPostList(user);
        // 关联用户与项目关联
        batchUserProjectList(user);
        return Result.success("操作成功");
    }

    /**
     * 修改保存用户信息
     *
     * @param user 用户信息
     * @return 结果
     */
    @Override
    @Transactional
    public Result updateUserInfo(SysUser user) {
        if (StringUtils.isNotBlank(user.getPassword())) {
            user.setPassword(SecureUtil.md5(user.getPassword()));
        }
        // 删除用户和项目关联
        if (SystemUtils.isAdmin(SecurityUtils.getUserId())) {
            userProjectMapper.deleteUserProjectId(null, user.getUserId());
        } else {
            userProjectMapper.deleteUserProjectId(user.getSysCode(), user.getUserId());
        }
        // 关联用户与项目关联
        batchUserProjectList(user);
        // 删除用户与岗位关联
        userPostMapper.deleteUserPostById(user.getUserId());
        // 新增用户与岗位管理
        batchUserPostList(user);
        // 修改绑定账户授权状态
        updateAuthState(user);
        // 删除用户缓存信息
        String userKey = String.valueOf(user.getUserId());
        redisService.delHashKey(GlobalConstants.sysUserInfo, userKey);
        userMapper.updateById(user);
        return Result.success("操作成功");
    }

    /**
     * 关联用户角色信息
     */
    @Override
    public Result updateUserProject(SysUser user) {
        // 删除用户和项目关联
        if (SystemUtils.isAdmin(SecurityUtils.getUserId())) {
            userProjectMapper.deleteUserProjectId(null, user.getUserId());
        } else {
            userProjectMapper.deleteUserProjectId(user.getSysCode(), user.getUserId());
        }
        // 删除用户与岗位关联
        userPostMapper.deleteUserPostById(user.getUserId());
        // 新增用户与岗位管理
        batchUserPostList(user);
        // 关联用户与项目关联
        batchUserProjectList(user);
        return Result.success("操作成功");
    }

    /**
     * 修改用户状态
     *
     * @param user 用户信息
     * @return 结果
     */
    @Override
    public int updateUserStatus(SysUser user) {
        // 修改绑定账户授权状态
        updateAuthState(user);
        return userMapper.updateById(user);
    }

    /**
     * 修改用户基本信息
     *
     * @param user 用户信息
     * @return 结果
     */
    @Override
    public int updateUserProfile(SysUser user) {
        // 删除Redis用户缓存信息
        String userKey = String.valueOf(user.getUserId());
        redisService.delHashKey(GlobalConstants.sysUserInfo, userKey);
        return userMapper.updateById(user);
    }

    /**
     * 修改用户头像
     *
     * @param userName 用户名
     * @param avatar   头像地址
     * @return 结果
     */
    @Override
    public boolean updateUserAvatar(String userName, String avatar) {
        return userMapper.updateUserAvatar(userName, avatar) > 0;
    }

    /**
     * 重置用户密码
     *
     * @param user 用户信息
     * @return 结果
     */
    @Override
    public int resetPwd(SysUser user) {
        // 获取系统密码
        if (StringUtils.isNotEmpty(user.getPassword())) {
            user.setPassword(SecureUtil.md5(user.getPassword()));
        } else {
            String oldPassword = ConfigUtils.getConfigInfo("sys.old.password");
            user.setPassword(SecureUtil.md5(oldPassword));
        }
        return userMapper.updateById(user);
    }

    /**
     * 重置用户密码
     *
     * @param userName 用户名
     * @param password 密码
     * @return 结果
     */
    @Override
    public int resetUserPwd(String userName, String password) {
        return userMapper.resetUserPwd(userName, password);
    }

    /**
     * 关联用户与项目信息
     *
     * @param user 用户对象
     */
    private int batchUserProjectList(SysUser user) {
        int rows = 1;
        // 新增用户与项目关联
        if (StringUtils.isNotNull(user.getRoleIds())) {
            // 新增用户与项目关联
            List<SysUserProject> userProjectList = new ArrayList<>();
            for (Long roleId : user.getRoleIds()) {
                SysUserProject userProject = new SysUserProject();
                userProject.setUserId(user.getUserId());
                // 查询项目未关联角色,则创建关联记录
                SysProjectRole proRole = new SysProjectRole();
                proRole.setSysCode(user.getSysCode());
                proRole.setRoleId(roleId);
                SysProjectRole projectRole = projectRoleMapper.selectProjectRole(proRole);
                if (StringUtils.isNull(projectRole)) {
                    throw new CustomException("操作失败:关联项目角色不存在");
                }
                userProject.setPrId(projectRole.getPrId());
                // 判断用户与项目关联数量是否存在
                int countNum = userProjectMapper.checkUserProjectNum(userProject);
                if (countNum <= 0) {
                    userProjectList.add(userProject);
                }
            }
            if (userProjectList.size() > 0) {
                rows = userProjectMapper.batchUserProject(userProjectList);
            }
        }
        return rows;
    }

    /**
     * 新增用户岗位信息
     *
     * @param user 用户对象
     */
    private int batchUserPostList(SysUser user) {
        int rows = 1;
        // 新增用户与岗位管理
        if (StringUtils.isNotNull(user.getPostIds())) {
            List<SysUserPost> userPostList = new ArrayList<>();
            for (Long postId : user.getPostIds()) {
                SysUserPost userPost = new SysUserPost();
                userPost.setUserId(user.getUserId());
                userPost.setPostId(postId);
                userPostList.add(userPost);
            }
            if (userPostList.size() > 0) {
                rows = userPostMapper.batchUserPost(userPostList);
            }
        }
        return rows;
    }

    /**
     * 通过用户ID删除用户
     *
     * @param userId 用户ID
     * @return 结果
     */
    @Override
    @Transactional
    public int deleteUserById(Long userId) {
        // 删除Redis用户缓存信息
        String userKey = String.valueOf(userId);
        redisService.delHashKey(GlobalConstants.sysUserInfo, userKey);
        // 删除用户与岗位表
        userPostMapper.deleteUserPostById(userId);
        return userMapper.deleteById(userId);
    }

    /**
     * 批量删除用户信息
     *
     * @param userIds 需要删除的用户ID
     * @return 结果
     */
    @Override
    @Transactional
    public int deleteUserByIds(List<Long> userIds) {
        // 删除用户与项目关联
        userProjectMapper.deleteUserProject(userIds);
        // 删除用户与岗位关联
        userPostMapper.deleteUserPost(userIds);
        return userMapper.deleteBatchIds(userIds);
    }

    /**
     * 根据授权信息获取用户信息
     */
    @Override
    public SysUser selectUserByAuth(AuthBody authBody) {
        return userMapper.selectUserByAuth(authBody);
    }

    /**
     * 查询用户通讯录列表
     *
     * @return
     */
    @Override
    public List<UserBook> getUserBookList(String nickName) {
        List<UserBook> userBookList = userMapper.selectUserBookList(nickName);
        if (userBookList.size() > 0) {
            for (UserBook userBook : userBookList) {
                userBook.setAvatar(annexUrlService.getImageTurnPath(userBook.getAvatar()));
            }
        }
        return userMapper.selectUserBookList(nickName);
    }

    /**
     * 根据部门主键查询用户主键列表
     *
     * @param deptId
     * @return
     */
    @Override
    public String selectUserIds(Long deptId) {
        return userMapper.selectUserIds(deptId);
    }

    /**
     * 查询下拉选择用户列表
     *
     * @return
     */
    @Override
    @DataScope(deptAlias = "d", userAlias = "u")
    public List<OptionUser> selectOptionUserList(SysUser user) {
        return userMapper.selectOptionUserList(user);
    }

    /**
     * 导出用户列表
     *
     * @param user
     */
    @Override
    public void exportUserList(SysUser user) {
        PageHelper.startPage(ExcelPoiConstants.startNum, ExcelPoiConstants.maxSize);
        List<SysUser> sysUserList = userMapper.selectUserList(user);
        PageHelper.clearPage();
        if (sysUserList.size() > 0) {
            sysUserList.forEach(sysUser -> {
                sysUser.setUserAuthList(userAuthService.selectUserAuthById(sysUser.getUserId()));
            });
        }
        String titleName = "系统账户列表";
        ExcelPoiUtils.exportExcel(sysUserList, titleName, "sys_user_info",
                SysUser.class, titleName + ".xls", ServletUtils.getResponse());
    }

    /**
     * 导入用户信息
     *
     * @param file
     * @param updateSupport
     * @return
     */
    @Override
    @Transactional
    public String importUserListData(MultipartFile file, boolean updateSupport) {
        List<SysUser> sysUserList = ExcelPoiUtils.importExcel(file, 1, 2, SysUser.class);
        if (StringUtils.isNull(sysUserList) || sysUserList.size() == 0) {
            throw new CustomException("导入用户数据不能为空！");
        }
        String oldPassword = ConfigUtils.getConfigInfo("sys.old.password");
        int successNum = 0;
        int failureNum = 0;
        StringBuilder successMsg = new StringBuilder();
        StringBuilder failureMsg = new StringBuilder();
        List<SysUserAuth> userAuthList = new ArrayList<>();
        for (SysUser user : sysUserList) {
            try {
                // 验证是否存在这个用户
                int count = userMapper.checkUserNameUnique(user.getUserName());
                if (count <= 0) {
                    if (StringUtils.isNotEmpty(user.getDeptName())) {
                        // 根据部门全称获取部门主键
                        SysDept sysDept = deptMapper.selectDeptByName(user.getDeptName());
                        if (StringUtils.isNotNull(sysDept)) {
                            user.setDeptId(sysDept.getDeptId());
                        }
                    }
                    // 添加系统账户信息
                    user.setPassword(oldPassword);
                    insertUserInfo(user);
                    successNum++;
                    successMsg.append("<br/>" + successNum + ",账号:" + user.getUserName() + "导入成功");
                    // 添加第三方账户授权信息
                    if (user.getUserAuthList().size() > 0) {
                        for (SysUserAuth userAuth : user.getUserAuthList()) {
                            userAuth.setUserId(user.getUserId());
                            userAuthList.add(userAuth);
                        }
                    }
                } else if (updateSupport) {
                    updateUserInfo(user);
                    successNum++;
                    successMsg.append("<br/>" + successNum + ",账号 " + user.getUserName() + "更新成功");
                } else {
                    failureNum++;
                    failureMsg.append("<br/>" + failureNum + ",账号 " + user.getUserName() + "已存在");
                }
            } catch (Exception e) {
                failureNum++;
                String msg = "<br/>" + failureNum + ",账号 " + user.getUserName() + "导入失败：";
                failureMsg.append(msg + e.getMessage());
                log.error(msg, e);
            }
        }
        if (userAuthList.size() > 0) {
            // 添加用户授权列表
            userAuthService.saveBatch(userAuthList);
        }
        if (failureNum > 0) {
            failureMsg.insert(0, "很抱歉,导入失败!共" + failureNum + "条数据格式不正确,错误如下:");
            throw new CustomException(failureMsg.toString());
        } else {
            successMsg.insert(0, "恭喜您,数据已全部导入成功!共 " + successNum + "条,数据如下:");
        }
        return successMsg.toString();
    }

    /**
     * 根据用户修改用户授权状态
     *
     * @param user
     */
    private void updateAuthState(SysUser user) {
        SysUserAuth userAuth = new SysUserAuth();
        userAuth.setUserId(user.getUserId());
        if (UserStatus.OK.getCode() == user.getStatus()) {
            userAuth.setAuthState(UserAuthStatus.ENABLE.getCode());
        } else {
            userAuth.setAuthState(UserAuthStatus.DEACTIVATE.getCode());
        }
        userAuthMapper.updateStateByUserId(userAuth);
    }

    /**
     * 根据昵称或电话查询账户信息
     *
     * @param phone
     * @return
     */
    @Override
    public SysUser queryUserInfo(String phone) {
        return userMapper.queryUserInfo(phone);
    }

    /**
     * 根据账户查询信息
     *
     * @param userName
     * @return
     */
    @Override
    public SysUser selectUserByName(String userName) {
        return userMapper.selectUserByName(userName);
    }

}
